﻿#pragma once
#include <QString>
#include <QLibrary>
#include <QProcessEnvironment>
#include <QDir>
#include <QDebug>
#include <QFile>
#include <QMap>
#include <QDateTime>
#include "BaseSer.h"
#include "BaseUi.h"
//日志记录器
class Logger{
private:
	QFile logFile;
	bool appendLog(const QString& componentName,const QString& msg,char level='D');
public:
	Logger(const QString& logPath);
	~Logger();
	QString path(){return logFile.fileName();}
	bool d(const QString& componentName,const QString& msg);//debug
	bool i(const QString& componentName,const QString& msg);//info
	bool e(const QString& componentName,const QString& msg);//error
	bool v(const QString& componentName,const QString& msg);//verbose
	bool w(const QString& componentName,const QString& msg);//warn
};
//用来管理SerLoad或者ViewLoad的抽象类
//主要是借助c++的运行时多态（使用父类指针执行子类的函数）
//可以避免用户在操作界面那一块，代码里用到大量的 if-else 判断
class ILoadManager
{
protected:
	QString mComName;//组件名
	Logger* logger;//日志记录器
	QLibrary mLib;//控制dll文件的加载和卸载
	QMap<QString,QString> mStateMap;//各个实例当前所处的状态。键是实例名，值是实例所处的状态
	static QDir sLibDir;//组件库所在目录,该静态变量需要在类外初始化。见ILoadManager.cpp
public:
	ILoadManager(const QString& dllName,Logger* logger=nullptr);//加载动态链接库
	void setLogger(Logger* logger);//设置日志保存文件
	//父类的析构函数一般写成虚函数
	virtual ~ILoadManager(void);//卸载动态链接库
	//以下几个虚函数子类可以选择是否重写
	virtual const QString QueryState(const QString& instanceName);//查询组件实例所处的状态，如果指定的实例名不存在，则默认返回UnLoaded
	virtual const QString& GetComponentName();//获取组件的名称
	//以下几个纯虚函数需要子类去实现
	virtual void Load(void* ptrLoad)=0;//创建组件的实例，ptrLoad为ViewLoad指针或者SerLoad指针，会在子类中重写的方法里进行向下转型，具体传入什么类型取决于子类的类型
	virtual void Init(const QString& instanceName)=0;//初始化组件实例
	virtual void Active(const QString& instanceName)=0;//激活组件实例,如果组件带UI，会同时显示出该组件
	virtual void UnActive(const QString& instanceName)=0;//去活组件实例,如果组件带UI，会同时隐藏该组件
	virtual void UnLoad(const QString& instanceName)=0;//卸载组件实例，内部会调用组件的Free函数和析构函数
};
//用来管理SerLoad的类
class SerLoadManager:public ILoadManager
{
private:
	QMap<QString,SerLoad*> mSerLoadMap;
public:
	SerLoadManager(const QString& dllName,Logger* logger=nullptr):ILoadManager(dllName,logger){};
	~SerLoadManager(){};
	void Load(SerLoad* ptrSerLoad);
	virtual void Load(void* ptrSerLoad)override;
	virtual void Init(const QString& instanceName)override;
	virtual void Active(const QString& instanceName)override;
	virtual void UnLoad(const QString& instanceName)override;
	virtual void UnActive(const QString& instanceName)override;
};
//用来管理ViewLoad的类
class ViewLoadManager:public ILoadManager
{
private:
	QMap<QString,ViewLoad*> mViewLoadMap;
	QWidget* mParent;
public:
	ViewLoadManager(const QString& dllName,QWidget* parent,Logger* logger=nullptr):ILoadManager(dllName,logger),mParent(parent){};
	~ViewLoadManager(){};
	void Load(ViewLoad* ptrViewLoad);
	virtual void Load(void* ptrViewLoad)override;
	virtual void Init(const QString& instanceName)override;
	virtual void Active(const QString& instanceName)override;
	virtual void UnLoad(const QString& instanceName)override;
	virtual void UnActive(const QString& instanceName)override;
};